// 线程池的实现与封装
#include "Mutex.hpp"
#include "Thread.hpp"
#include "Log.hpp"
#include "Cond.hpp"
#include <vector>
#include <queue>

namespace ThreadPoolModule
{
    using namespace MutexModule;
    using namespace LogModule;
    using namespace ThreadModule;
    using namespace CondModule;

    template <typename T>
    class ThreadPool
    {
    private:
        void WakeUpAll()
        {
            LockGuard lockgurad(_mutex);
            if (_sleepnum > 0)
            {
                _cond.Broadcast();
                LOG(LogLevel::INFO) << "唤醒当前休眠的所有线程";
            }
        }

        void WakeUpOne()
        {
            _cond.Signal();
            LOG(LogLevel::INFO) << "唤醒当前休眠的一个线程";
        }

    public:
        ThreadPool(int num)
            : _num(num), _isrunning(false), _sleepnum(0)
        {
            for (int i = 0; i < num; i++)
            {
                // Lambda表达式
                _threads.emplace_back([this]()
                                      { HandlerTask(); });
            }
        }

        void HandlerTask()
        {
            char name[128];
            // 获取对应线程的名字
            pthread_getname_np(pthread_self(), name, sizeof(name));
            while (true)
            {
                T t;
                {
                    LockGuard LockGuard(_mutex);
                    // 1.任务队列为空 && 线程池正常运行
                    while (_task.empty() && _isrunning)
                    {
                        _sleepnum++;
                        _cond.Wait(_mutex);
                        _sleepnum--;
                    }

                    // 2.线程池终止 && 任务队列为空时；线程池才能退出
                    if (!_isrunning && _task.empty())
                    {
                        LOG(LogLevel::INFO) << "线程池终止并退出";
                        break;
                    }

                    // 这里一定有任务
                    t = _task.front();
                    _task.pop();
                }
                t(); // 锁外处理任务
            }
        }

        // 传入方法
        void Equeue(const T &in)
        {
            LockGuard lockguard(_mutex);
            if (_isrunning)
            {
                _task.push(in);
                // 当所有的线程都休眠了，需要唤醒线程
                if (_num == _sleepnum)
                {
                    WakeUpOne();
                }
            }
        }

        void Join()
        {
            for (auto &thread : _threads)
            {
                thread.Join();
            }
            LOG(LogLevel::INFO) << "全部线程等待完毕";
        }

        void Stop()
        {
            if (!_isrunning)
                return;
            _isrunning = false;

            // 唤醒所有线程
            WakeUpAll();
        }

        void Start()
        {
            _isrunning = true;
            for (auto &thread : _threads)
            {
                thread.Start();
            }
        }

    private:
        int _num;                     // 线程数量
        std::vector<Thread> _threads; // 线程
        std::queue<T> _task;          // 任务队列
        Cond _cond;
        Mutex _mutex;

        bool _isrunning;
        int _sleepnum; // 休眠线程个数
    };
}